package org.locker.service.impl;

import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.commons.codec.digest.DigestUtils;
import org.locker.common.core.utils.MapstructUtils;
import org.locker.common.core.utils.StringUtils;
import org.locker.common.mybatis.core.page.PageQuery;
import org.locker.common.mybatis.core.page.TableDataInfo;
import org.locker.common.oss.core.OssClient;
import org.locker.common.oss.factory.OssFactory;
import org.locker.domain.Device;
import org.locker.domain.DeviceVersion;
import org.locker.domain.bo.DeviceVersionBo;
import org.locker.domain.enums.DeviceStatusEnum;
import org.locker.domain.vo.DeviceVersionVo;
import org.locker.mapper.DeviceVersionMapper;
import org.locker.netty.MachineService;
import org.locker.service.IDeviceService;
import org.locker.service.IDeviceVersionService;
import org.locker.system.domain.vo.SysOssVo;
import org.locker.system.service.ISysOssService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 设备升级信息Service业务层处理
 *
 * @author winnie
 * @date 2023-10-11
 */
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
@Service
public class DeviceVersionServiceImpl extends ServiceImpl<DeviceVersionMapper, DeviceVersion> implements IDeviceVersionService {

    private final DeviceVersionMapper baseMapper;
    private final ISysOssService sysOssService;
    private final IDeviceService iDeviceService;
    private final MachineService machineService;

    /**
     * 查询设备升级信息
     */
    @Override
    public DeviceVersionVo queryById(Long deviceVersionId) {
        return baseMapper.selectVoById(deviceVersionId);
    }

    /**
     * 查询设备升级信息列表
     */
    @Override
    public TableDataInfo<DeviceVersionVo> queryPageList(DeviceVersionBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<DeviceVersion> lqw = buildQueryWrapper(bo);
        Page<DeviceVersionVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询设备升级信息列表
     */
    @Override
    public List<DeviceVersionVo> queryList(DeviceVersionBo bo) {
        LambdaQueryWrapper<DeviceVersion> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<DeviceVersion> buildQueryWrapper(DeviceVersionBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<DeviceVersion> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getVersionName()), DeviceVersion::getVersionName, bo.getVersionName());
        lqw.eq(StringUtils.isNotBlank(bo.getVersionCode()), DeviceVersion::getVersionCode, bo.getVersionCode());
        lqw.eq(StringUtils.isNotBlank(bo.getFileUrl()), DeviceVersion::getFileUrl, bo.getFileUrl());
        lqw.eq(StringUtils.isNotBlank(bo.getFileMd5()), DeviceVersion::getFileMd5, bo.getFileMd5());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), DeviceVersion::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getMiniVersionCode()), DeviceVersion::getMiniVersionCode, bo.getMiniVersionCode());
        lqw.eq(StringUtils.isNotBlank(bo.getFileChannel()), DeviceVersion::getFileChannel, bo.getFileChannel());
        return lqw;
    }

    /**
     * 新增设备升级信息
     */
    @Override
    public Boolean insertByBo(DeviceVersionBo bo) {
        DeviceVersion add = MapstructUtils.convert(bo, DeviceVersion.class);

        if (StringUtils.isNotBlank(bo.getFileUrl())) {
            SysOssVo sysOss = sysOssService.getById(Long.valueOf(bo.getFileUrl()));
            OssClient storage = OssFactory.instance(sysOss.getService());
            try {
                String md5Hex = DigestUtils.md5Hex(storage.getObjectContent(sysOss.getUrl()));
                add.setFileMd5(md5Hex);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }


        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setDeviceVersionId(add.getDeviceVersionId());
        }
        return flag;
    }

    /**
     * 修改设备升级信息
     */
    @Override
    public Boolean updateByBo(DeviceVersionBo bo) {
        DeviceVersion update = MapstructUtils.convert(bo, DeviceVersion.class);

        if (StringUtils.isNotBlank(bo.getFileUrl())) {
            SysOssVo sysOss = sysOssService.getById(Long.valueOf(bo.getFileUrl()));
            OssClient storage = OssFactory.instance(sysOss.getService());
            try {
                String md5Hex = DigestUtils.md5Hex(storage.getObjectContent(sysOss.getUrl()));
                update.setFileMd5(md5Hex);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DeviceVersion entity) {
        //做一些数据校验,如唯一约束
    }

    /**
     * 批量删除设备升级信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    @Lock4j(keys = "pushVersionUpdate", expire = 3000, acquireTimeout = 5000)
    public void pushVersionUpdate() {
        List<Device> devices = iDeviceService.list(Wrappers.lambdaQuery(Device.class)
            .eq(Device::getStatus, DeviceStatusEnum.online.getCode())
        );
        for (Device device : devices) {
            machineService.pushVersion(device.getDeviceNo());
        }
    }
}
